home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_126 / suplib / xfio.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  6KB  |  251 lines

  1.  
  2. /*
  3.  *  XFIO.C
  4.  *
  5.  *  Simple File IO with asyncronous READ and WRITE capability
  6.  *  Perfect for protocol transfer applications
  7.  *
  8.  *  xfi = xfopen(name, modes, bufsize)    ("r", "w", "w+")
  9.  *   n    = xfread(xfi, buf, bytes)   ASYNCRONOUS READ
  10.  *  err = xfwrite(xfi, buf, bytes)  ASYNCRONOUS WRITE
  11.  *  err = xfclose(xfi)
  12.  *
  13.  *  RESTRICTIONS:   NO seeking.  You can do one of xfread() or xfwrite()
  14.  *  for a given open XFIle handle (not both).
  15.  *
  16.  *  xfwrite() returns a cumulative error (once an error occurs, it will not
  17.  *  do any more writes).  xfclose() returns the cumulative write error
  18.  *  (since the last write may have been asyncronous and thus the error
  19.  *  unknown at the time).
  20.  *
  21.  *  Two buffers are created each bufsize/2 bytes in size.  for writing,
  22.  *  one buffers is sent asyncronously while the other fills.  For reading,
  23.  *  one buffer is filling while the other is being read.
  24.  */
  25.  
  26. #define XFI        struct _XFI
  27. #define XFBUF        struct _XFBUF
  28. #define MSGPORT     struct MsgPort
  29. #define FH        struct FileHandle
  30. #define STDPKT        struct StandardPacket
  31.  
  32.  
  33. XFBUF {
  34.     long   bufsize;
  35.     long   idx;
  36.     long   max;
  37.     char    buf[4];    /*  actually bufsize bytes long */
  38. };
  39.  
  40. XFI {
  41.     char    ro;     /*  read only, else write only    */
  42.     char    pend;    /*  packet pending        */
  43.     char    err;    /*  cumulative error        */
  44.     char    reserved;
  45.     XFBUF   *asbuf;
  46.     XFBUF   *usbuf;
  47.     FH        *fh;
  48.     STDPKT  sp;     /*  asyncronous message     */
  49.     MSGPORT rp;     /*  reply port for pending pkts */
  50. };
  51.  
  52. extern FH *Open();
  53. extern void *malloc(), *FindTask();
  54.  
  55. void *
  56. xfopen(file, mode, bytes)
  57. char *file;
  58. char *mode;
  59. {
  60.     register XFI *xfi = malloc(sizeof(XFI));
  61.     register long nbytes = bytes >> 1;
  62.     int ap = 0;
  63.  
  64.     bzero(xfi, sizeof(XFI));
  65.     if (mode[0] == 'w') {
  66.     if (mode[1] == '+') {
  67.         ap = 1;
  68.         if ((xfi->fh = Open(file, 1005)) == NULL)
  69.         xfi->fh = Open(file, 1006);
  70.         goto ok;
  71.     }
  72.     xfi->fh = Open(file, 1006);
  73.     goto ok;
  74.     }
  75.     xfi->fh = Open(file, 1005);
  76. ok:
  77.     if (xfi->fh) {
  78.     if (ap)
  79.         Seek(xfi->fh, 0, 1);
  80.     xfi->fh = (FH *)((long)xfi->fh << 2);
  81.     xfi->asbuf = malloc(sizeof(XFBUF) + nbytes);    /* a little more    */
  82.     xfi->usbuf = malloc(sizeof(XFBUF) + nbytes);    /* then we need     */
  83.     bzero(xfi->asbuf, sizeof(XFBUF));
  84.     bzero(xfi->usbuf, sizeof(XFBUF));
  85.     xfi->ro = (mode[0] == 'r');
  86.     xfi->asbuf->bufsize = xfi->usbuf->bufsize = nbytes;
  87.     xfi->rp.mp_Node.ln_Type = NT_MSGPORT;
  88.     xfi->rp.mp_Node.ln_Name = "XFIO-Async";
  89.     xfi->rp.mp_Flags = PA_SIGNAL;
  90.     xfi->rp.mp_SigBit = AllocSignal(-1);
  91.     xfi->rp.mp_SigTask = FindTask(NULL);
  92.     NewList(&xfi->rp.mp_MsgList);
  93.     if (xfi->ro)
  94.         xfstartasync(xfi, ACTION_READ);
  95.     } else {
  96.     free(xfi);
  97.     xfi = NULL;
  98.     }
  99.     return(xfi);
  100. }
  101.  
  102. xfclose(xfi)
  103. register XFI *xfi;
  104. {
  105.     int err = 1;
  106.     if (xfi) {
  107.     if (xfi->pend) {
  108.         xfi->pend = 0;
  109.         WaitPort (&xfi->rp);
  110.         GetMsg   (&xfi->rp);
  111.     }
  112.     if (!xfi->ro && xfi->usbuf->idx)
  113.         Write((long)xfi->fh >> 2, xfi->usbuf->buf, xfi->usbuf->idx);
  114.     err = xfi->err;
  115.     Close((long)xfi->fh >> 2);
  116.     free(xfi->asbuf);
  117.     free(xfi->usbuf);
  118.     FreeSignal(xfi->rp.mp_SigBit);
  119.     free(xfi);
  120.     }
  121.     return(err);
  122. }
  123.  
  124. xfgets(xfi, buf, n)
  125. XFI *xfi;
  126. char *buf;
  127. {
  128.     register XFBUF *usbuf = xfi->usbuf;
  129.     register int i, idx;
  130.     if (!xfi->ro)
  131.     return(-1);
  132.     --n;
  133.     for (i = 0;;) {
  134.     for (idx = usbuf->idx; idx < usbuf->max && i < n; ++idx, ++i) {
  135.         if ((buf[i] = usbuf->buf[idx]) == '\n') {
  136.         buf[i] = 0;
  137.         usbuf->idx = idx+1;
  138.         return(i);
  139.         }
  140.     }
  141.     usbuf->idx = idx;
  142.     buf[i] = 0;
  143.     if (i == n)
  144.         return(i);
  145.     if (xfi->pend == 0)                /* EOF        */
  146.         return(-1);
  147.     WaitPort (&xfi->rp);
  148.     GetMsg     (&xfi->rp);
  149.     xfi->pend = 0;
  150.     if (xfi->sp.sp_Pkt.dp_Res1 <= 0) {        /* EOF        */
  151.         if (i == 0)
  152.         return(-1);
  153.         return(i);
  154.     }
  155.     xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1;
  156.     xfi->asbuf->idx = 0;
  157.     usbuf = xfi->asbuf;                /* swap bufs*/
  158.     xfi->asbuf = xfi->usbuf;
  159.     xfi->usbuf = usbuf;
  160.     xfstartasync(xfi, ACTION_READ);         /* new async*/
  161.     }
  162. }
  163.  
  164.  
  165. xfread(xfi, buf, n)
  166. XFI *xfi;
  167. char *buf;
  168. {
  169.     register XFBUF *usbuf = xfi->usbuf;
  170.     register int orig = n;
  171.     register int diff;
  172.  
  173.     if (!xfi->ro)
  174.     return(0);
  175.     while ((diff = usbuf->max - usbuf->idx) < n) {
  176.     movmem(usbuf->buf + usbuf->idx, buf, diff);    /* copy entire buf */
  177.     buf += diff;
  178.     n -= diff;
  179.     if (xfi->pend == 0) {
  180.         xfi->usbuf->idx = xfi->usbuf->max;
  181.         return(orig - n);
  182.     }
  183.     WaitPort (&xfi->rp);
  184.     GetMsg     (&xfi->rp);
  185.     xfi->pend = 0;
  186.     if (xfi->sp.sp_Pkt.dp_Res1 <= 0) {        /* EOF        */
  187.         xfi->usbuf->idx = xfi->usbuf->max;
  188.         return(orig - n);
  189.     }
  190.     xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1;
  191.     xfi->asbuf->idx = 0;
  192.     usbuf = xfi->asbuf;                /* swap bufs*/
  193.     xfi->asbuf = xfi->usbuf;
  194.     xfi->usbuf = usbuf;
  195.     xfstartasync(xfi, ACTION_READ);         /* new async*/
  196.     }
  197.     movmem(usbuf->buf + usbuf->idx, buf, n);
  198.     usbuf->idx += n;
  199.     return(orig);
  200. }
  201.  
  202. xfwrite(xfi, buf, n)
  203. XFI *xfi;
  204. char *buf;
  205. {
  206.     register XFBUF *usbuf = xfi->usbuf;
  207.     register int diff;
  208.  
  209.     if (xfi->ro || xfi->err)
  210.     return(1);
  211.     while ((diff = usbuf->bufsize - usbuf->idx) < n) {
  212.     movmem(buf, usbuf->buf + usbuf->idx, diff);    /*  copy buf    */
  213.     buf += diff;
  214.     n -= diff;
  215.     if (xfi->pend) {
  216.         WaitPort(&xfi->rp);
  217.         GetMsg  (&xfi->rp);
  218.         xfi->pend = 0;
  219.         if (xfi->sp.sp_Pkt.dp_Res1 != xfi->sp.sp_Pkt.dp_Arg3) {
  220.         xfi->err = 1;
  221.         return(1);
  222.         }
  223.     }
  224.     usbuf = xfi->asbuf;
  225.     xfi->asbuf = xfi->usbuf;
  226.     xfi->usbuf = usbuf;
  227.     usbuf->idx = 0;
  228.     xfstartasync(xfi, ACTION_WRITE);
  229.     }
  230.     movmem(buf, usbuf->buf + usbuf->idx, n);
  231.     usbuf->idx += n;
  232.     return(xfi->err);
  233. }
  234.  
  235. static
  236. xfstartasync(xfi, action)
  237. register XFI *xfi;
  238. {
  239.     xfi->sp.sp_Msg.mn_Node.ln_Name = (char *)&(xfi->sp.sp_Pkt);
  240.     xfi->sp.sp_Pkt.dp_Link = &(xfi->sp.sp_Msg);
  241.     xfi->sp.sp_Pkt.dp_Port = &xfi->rp;
  242.     xfi->sp.sp_Pkt.dp_Type = action;
  243.     xfi->sp.sp_Pkt.dp_Arg1 = xfi->fh->fh_Arg1;
  244.     xfi->sp.sp_Pkt.dp_Arg2 = (long)xfi->asbuf->buf;
  245.     xfi->sp.sp_Pkt.dp_Arg3 = xfi->asbuf->bufsize;
  246.     PutMsg (xfi->fh->fh_Type, &xfi->sp);
  247.     xfi->pend = 1;
  248. }
  249.  
  250.  
  251.